package xyz.gzdxc.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * cookie util
 * @author gzdxc
 * @date 2022/11/08
 */
public class CookieUtil {
    private static final Logger LOG = LoggerFactory.getLogger(CookieUtil.class);

    /** the default cache time, unit: s,  2 hours*/
    private static final int COOKIE_MAX_AGE = 60 * 60 * 2;

    /** the cookie save path, root path */
    private static final String COOKIE_PATH = "/";

    /**
     * get the cookie from the request
     *
     * @param request
     *          HttpServletRequest
     * @param key
     *          the key of the cookie
     * @return the value of the cookie
     */
    public static Cookie getCookie(HttpServletRequest request, String key){
        LOG.info("start get the cookie => {}", key);
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length > 0){
            for(Cookie cookie : cookies){
                if(key.equals(cookie.getName())){
                    LOG.info("got the cookie => {}", key);
                    return cookie;
                }
            }
        }
        LOG.info("cannot get the cookie => {}", key);
        return null;
    }

    /**
     * get the cookie value
     *
     * @param request
     *          HttpServletRequest
     * @param key
     *          the key of the cookie
     * @return the value of the cookie
     */
    public static String getCookieValue(HttpServletRequest request, String key){
        Cookie cookie = getCookie(request, key);
        if(cookie != null){
            LOG.info("got the cookie, key => {},  value => {}", key, cookie.getValue());
            return cookie.getValue();
        }
        return null;
    }

    /**
     * set the cookie
     *
     * @param response
     *          HttpServletResponse
     * @param key
     *          the key of the cookie
     * @param value
     *          the value of the cookie
     * @param comment
     *          the comment of the cookie
     * @param domain
     *          the domain where the cookie can present
     * @param isHttpOnly
     *          whether the cookie can only used by the server or not
     * @param maxAge
     *          the cookie's timeout, unit: s
     * @param path
     *          the path of the cookie
     * @param isSecure
     *          whether the cookie can only use HTTPS/SSL
     * @param version
     *          the version of the cookie
     */
    private static void setCookie(HttpServletResponse response, String key, String value, String comment, String domain,
                            boolean isHttpOnly, int maxAge, String path, boolean isSecure, int version){

        Cookie cookie = new Cookie(key, value);
        if (comment != null && !comment.trim().isEmpty()) {
            // set the cookie's comment
            cookie.setComment(comment);
        }

        if (domain != null && !domain.trim().isEmpty()) {
            // set the cookie's domain where this cookie can display
            cookie.setDomain(domain);
        }

        if (path != null && !path.trim().isEmpty()) {
            // set the cookie's path
            cookie.setPath(path);
        }

        // set the cookie whether can only be used by server
        cookie.setHttpOnly(isHttpOnly);
        // set the cookie's timeout second
        cookie.setMaxAge(maxAge);
        // set the cookie whether can only use HTTPS/SSL
        cookie.setSecure(isSecure);
        // set the cookie's version
        cookie.setVersion(version);

        LOG.info("key => {}", cookie.getName());
        LOG.info("value => {}", cookie.getValue());
        LOG.info("comment => {}", cookie.getComment());
        LOG.info("domain => {}", cookie.getDomain());
        LOG.info("isHttpOnly => {}", cookie.isHttpOnly());
        LOG.info("maxAge => {}", cookie.getMaxAge());
        LOG.info("path => {}", cookie.getPath());
        LOG.info("isSecure => {}", cookie.getSecure());
        LOG.info("version => {}", cookie.getVersion());

        response.addCookie(cookie);
    }

    /**
     * set the cookie
     *
     * @param response
     *          HttpServletResponse
     * @param key
     *          the key of the cookie
     * @param value
     *          the value of the cookie
     */
    public static void setCookie(HttpServletResponse response, String key, String value) {
        setCookie(response, key, value, "", "", false, COOKIE_MAX_AGE, COOKIE_PATH, false, 0);
    }

    /**
     * set the cookie
     *
     * @param response
     *          HttpServletResponse
     * @param key
     *          the key of the cookie
     * @param value
     *          the value of the cookie
     * @param isHttpOnly
     *          whether only server can modify the cookie
     */
    public static void setCookie(HttpServletResponse response, String key, String value, boolean isHttpOnly) {
        setCookie(response, key, value, "", "", isHttpOnly, COOKIE_MAX_AGE, COOKIE_PATH, false, 0);
    }

    /**
     * set the cookie
     *
     * @param response
     *          HttpServletResponse
     * @param key
     *          the key of the cookie
     * @param value
     *          the value of the cookie
     * @param maxAge
     *          the cookie's timeout, unit: s
     */
    public static void setCookie(HttpServletResponse response, String key, String value, int maxAge) {
        setCookie(response, key, value, "", "", false, maxAge, COOKIE_PATH, false, 0);
    }

    /**
     * remove the cookie
     * @param request
     *          HttpServletRequest
     * @param response
     *          HttpServletResponse
     * @param key
     *          the key of the cookie
     */
    public static void removeCookie(HttpServletRequest request, HttpServletResponse response, String key){
        LOG.info("remove the cookie start, key => {}", key);
        Cookie cookie = getCookie(request, key);
        if(cookie != null){
            setCookie(response, key, "", 0);
            LOG.info("remove the cookie end, key => {}", key);
        }
    }

}
